import sounddevice as sd
from typing import Dict, List, Optional, Tuple


class AudioDeviceManager:
    def __init__(self):
        self.input_devices = {}
        self.output_devices = {}
        self.input_mapping = {}  # 内部输入ID -> 设备ID
        self.output_mapping = {}  # 内部输出ID -> 设备ID
        self.scan_devices()
        # 修复：调用正确的方法名
        self._setup_default_mapping()

    def scan_devices(self):
        """扫描系统音频设备"""
        try:
            # 清空现有设备字典
            self.input_devices = {}
            self.output_devices = {}

            # 使用 sounddevice 查询所有设备
            devices = sd.query_devices()
            hostapis = sd.query_hostapis()

            for i, dev in enumerate(devices):
                # 检查设备是否可用于输入（麦克风）
                if dev['max_input_channels'] > 0:
                    device_id = f"input_{i}"
                    self.input_devices[device_id] = {
                        'id': device_id,
                        'name': dev['name'],
                        'index': i,  # 存储设备索引，sounddevice 通过索引指定设备
                        'channels': dev['max_input_channels'],
                        'hostapi': hostapis[dev['hostapi']]['name'],
                        'default_samplerate': dev['default_samplerate']
                    }

                # 检查设备是否可用于输出（扬声器）
                if dev['max_output_channels'] > 0:
                    device_id = f"output_{i}"
                    self.output_devices[device_id] = {
                        'id': device_id,
                        'name': dev['name'],
                        'index': i,  # 存储设备索引
                        'channels': dev['max_output_channels'],
                        'hostapi': hostapis[dev['hostapi']]['name'],
                        'default_samplerate': dev['default_samplerate']
                    }

            print(f"扫描到 {len(self.input_devices)} 个输入设备和 {len(self.output_devices)} 个输出设备")

        except Exception as e:
            print(f"扫描音频设备时出错: {e}")
            self._setup_fallback_devices()

    def _setup_default_mapping(self):
        """设置默认设备映射"""
        # 输入映射：内部ID 0 -> 第一个输入设备
        if self.input_devices:
            first_input = list(self.input_devices.keys())[0]
            self.input_mapping = {0: first_input}
        else:
            self.input_mapping = {0: 'default_input'}

        # 输出映射：内部ID 0 -> 第一个输出设备
        if self.output_devices:
            first_output = list(self.output_devices.keys())[0]
            self.output_mapping = {0: first_output}
        else:
            self.output_mapping = {0: 'default_output'}

        print(f"默认输入映射: {self.input_mapping}")
        print(f"默认输出映射: {self.output_mapping}")

    def _setup_fallback_devices(self):
        """设置回退设备"""
        self.input_mapping = {0: 'default_input'}
        self.output_mapping = {0: 'default_output'}
        print("使用回退设备配置")

    def get_input_device(self, internal_id: int):
        """根据内部ID获取输入设备索引"""
        device_key = self.input_mapping.get(internal_id)
        if device_key and device_key in self.input_devices:
            return self.input_devices[device_key]['index']  # 返回设备索引
        return None

    def get_output_device(self, internal_id: int):
        """根据内部ID获取输出设备索引"""
        device_key = self.output_mapping.get(internal_id)
        if device_key and device_key in self.output_devices:
            return self.output_devices[device_key]['index']  # 返回设备索引
        return None

    def get_available_inputs(self) -> List[Dict]:
        """获取可用的输入设备列表"""
        return list(self.input_devices.values())

    def get_available_outputs(self) -> List[Dict]:
        """获取可用的输出设备列表"""
        return list(self.output_devices.values())

    def get_input_mapping(self) -> List[Tuple[int, str, str]]:
        """获取输入映射表：内部ID, 设备ID, 设备名称"""
        mapping = []
        for internal_id, device_id in self.input_mapping.items():
            device_name = self.input_devices.get(device_id, {}).get('name', '未知设备')
            mapping.append((internal_id, device_id, device_name))
        return sorted(mapping, key=lambda x: x[0])  # 按内部ID排序

    def get_output_mapping(self) -> List[Tuple[int, str, str]]:
        """获取输出映射表：内部ID, 设备ID, 设备名称"""
        mapping = []
        for internal_id, device_id in self.output_mapping.items():
            device_name = self.output_devices.get(device_id, {}).get('name', '未知设备')
            mapping.append((internal_id, device_id, device_name))
        return sorted(mapping, key=lambda x: x[0])  # 按内部ID排序

    def update_input_mapping(self, internal_id: int, device_id: str):
        """更新输入映射"""
        if device_id in self.input_devices or device_id == '':
            self.input_mapping[internal_id] = device_id

    def update_output_mapping(self, internal_id: int, device_id: str):
        """更新输出映射"""
        if device_id in self.output_devices or device_id == '':
            self.output_mapping[internal_id] = device_id

    def add_input_mapping(self) -> int:
        """添加新的输入映射，返回新的内部ID"""
        new_id = max(self.input_mapping.keys(), default=-1) + 1
        if self.input_devices:
            first_device = list(self.input_devices.keys())[0]
            self.input_mapping[new_id] = first_device
        else:
            self.input_mapping[new_id] = ''
        return new_id

    def add_output_mapping(self) -> int:
        """添加新的输出映射，返回新的内部ID"""
        new_id = max(self.output_mapping.keys(), default=-1) + 1
        if self.output_devices:
            first_device = list(self.output_devices.keys())[0]
            self.output_mapping[new_id] = first_device
        else:
            self.output_mapping[new_id] = ''
        return new_id

    def remove_input_mapping(self, internal_id: int):
        """移除输入映射"""
        if internal_id in self.input_mapping:
            del self.input_mapping[internal_id]

    def remove_output_mapping(self, internal_id: int):
        """移除输出映射"""
        if internal_id in self.output_mapping:
            del self.output_mapping[internal_id]

    def get_serializable_data(self):
        """获取可序列化的设备数据"""
        return {
            'input_mapping': self.input_mapping,
            'output_mapping': self.output_mapping,
            'available_inputs': {k: v['name'] for k, v in self.input_devices.items()},
            'available_outputs': {k: v['name'] for k, v in self.output_devices.items()}
        }

    def load_from_data(self, data):
        """从数据加载设备配置"""
        if 'input_mapping' in data:
            # 将字符串键转换为整数
            self.input_mapping = {int(k): v for k, v in data['input_mapping'].items()}
        if 'output_mapping' in data:
            self.output_mapping = {int(k): v for k, v in data['output_mapping'].items()}